namespace cpputils
{

template<class TYPE>
class subarray
{
public:
	typedef TYPE value_type;

	subarray() : Ptr(0), Size(0)
	{
	}
	template<class T>
	subarray(const T& Val)
		: Ptr(begin_ptr(Val)), Size(Val.size())
	{
	}
	template<class T>
	subarray(T& Val)
		: Ptr(begin_ptr(Val)), Size(Val.size())
	{
	}
	subarray(TYPE* SetPtr, int SetSize)
		: Ptr(SetPtr), Size(SetSize)
	{
		assert(SetSize >= 0);
	}
	subarray(TYPE* Begin, TYPE* End)
		: Ptr(Begin), Size(End - Begin)
	{
		assert(Begin <= End);
	}
	subarray<TYPE> slice(int Begin, int Len) const
	{
		assert(Begin >= 0 && Len >= 0 && Begin + Len <= Size);
		return subarray<TYPE>(Ptr + Begin, Len);
	}
	subarray<TYPE> slice_to(int Begin, int End) const
	{
		assert(Begin >= 0 && End <= Size && Begin <= End);
		return subarray<TYPE>(Ptr + Begin, End - Begin);
	}
	template<class TYPE2>
	subarray<TYPE2> convert() const
	{
		return subarray<TYPE2>((TYPE2*)Ptr, Size);
	}
	TYPE& operator[](int I) const
	{
		return Ptr[I];
	}
	bool empty() const
	{
		return Size == 0;
	}
	int size() const
	{
		return Size;
	}
	TYPE& front() const
	{
		return *Ptr;
	}
	TYPE& back() const
	{
		return Ptr[Size - 1];
	}
	TYPE* begin() const
	{
		return Ptr;
	}
	TYPE* end() const
	{
		return Ptr + Size;
	}
private:
	TYPE* Ptr;
	int Size;
};

template<class T>
inline subarray<const typename T::value_type> make_subarray(const T& Val)
{
	return subarray<const typename T::value_type>(Val);
}

template<class T>
inline subarray<typename T::value_type> make_subarray(T& Val)
{
	return subarray<typename T::value_type>(Val);
}

template<class TYPE>
inline subarray<TYPE> make_subarray(TYPE* SetPtr, int SetSize)
{
	return subarray<TYPE>(SetPtr, SetSize);
}

template<class TYPE>
inline subarray<TYPE> make_subarray(TYPE* Begin, TYPE* End)
{
	return subarray<TYPE>(Begin, End);
}

template<class T>
inline subarray<const typename T::value_type> make_subarray(const T& Val, int Begin, int Len)
{
	assert(Begin >= 0 && Len >= 0 && Begin + Len <= (int)Val.size());
	return subarray<const typename T::value_type>(begin_ptr(Val) + Begin, Len);
}

template<class T>
inline subarray<typename T::value_type> make_subarray(T& Val, int Begin, int Len)
{
	assert(Begin >= 0 && Len >= 0 && Begin + Len <= (int)Val.size());
	return subarray<typename T::value_type>(begin_ptr(Val) + Begin, Len);
}

template<class T>
inline subarray<const typename T::value_type> make_subarray_to(const T& Val, int Begin, int End)
{
	assert(Begin >= 0 && End <= (int)Val.size() && Begin <= End);
	return subarray<const typename T::value_type>(begin_ptr(Val) + Begin, End - Begin);
}

template<class T>
inline subarray<typename T::value_type> make_subarray_to(T& Val, int Begin, int End)
{
	assert(Begin >= 0 && End <= (int)Val.size() && Begin <= End);
	return subarray<typename T::value_type>(begin_ptr(Val) + Begin, End - Begin);
}

}
